<?php
# vim set:
# :set fdm=indent
/**
 * Mongodb change_log's collection helper
 * @author vanni.fan@achievo.com
 */
class change_log{
	private static $connect = null;
	private static $fields  = array(
		'type'=>'',
		'keys'=>array(),
		'is_active'=>1,
		'programme_id'=>0,
		'episode_id'=>array(),
		'is_publish'=>0
	);
	/**
	 * private function for a mongodb connection
	 */
	private static function connect(){
		if(is_null(self::$connect)){
			self::$connect = CommonUtils::getMongoDB();
		}
		return self::$connect;
	}

	/**
	 * Mongodb find
	 */
	public static function find(array $where){
		$db = self::connect();
		return $db -> find($where);
	}
	/**
	 * Mongodb remove
	 */
	public static function remove(array $where){
		$db = self::connect();
		return $db -> remove($where);
	}

	/**
	 * Insert new log to change_log table
	 * @param array $data
	 * @return array
	 */
	public static function insert(array $data){
		$data = array_merge(self::$fields,$data);

		if(!trim($data['type']) || !count($data['keys'])){
			throw new Exception('The change_log key "type" and "keys" can\'t be null.');
		}
		foreach($data['keys'] as $k => &$v){
			$v = strval($v);
		}

		$fields = self::$fields;
		unset($v, $fields['type'], $fields['keys'], $fields['episode_id']);
		foreach($fields as $k=>$v){
			$data[$k] = intval($data[$k]);
		}
		if(empty($data['episode_id'])) $data['episode_id'] = array();
		elseif(!is_array($data['episode_id'])) $data['episode_id'] = array( $data['episode_id'] );
		foreach($data['episode_id'] as &$v) $v = intval($v);
		unset($v);

		$db = self::connect();
		self::filterKeys($data);
		return $db -> insert($data);
	}

	/**
	 * Update a record, if this record not exists then insert.
	 * @param array $data
	 * @return array
	 */
	public static function updateOne(array $data){
		$data['programme_id'] = isset($data['programme_id']) ? $data['programme_id'] : 0;
		$data['episode_id'] = empty($data['episode_id']) ? array() : $data['episode_id'];
		if(!is_array($data['episode_id'])) $data['episode_id'] = array( $data['episode_id'] );
		foreach($data['episode_id'] as &$v) $v = intval($v);
		unset($v);

		if(!trim($data['type']) || !count($data['keys'])){
			throw new Exception('The change_log key "type" and "keys" can\'t be null.');
		}
		
		$db = self::connect();

		$where = array('type'=>$data['type']);
		foreach($data['keys'] as $k => &$v){
			$v = strval($v);
			$where["keys.$k"] = $v;
		}

		$rs = $db -> findOne($where);
		if($rs){ // hasRecord
			$new_data = array_merge($rs,$data);
			$fields   = self::$fields;

			unset($v, $fields['type'], $fields['keys'], $fields['episode_id']);
			foreach($fields as $k=>$v){
				$new_data[$k] = intval($new_data[$k]);
			}
			self::filterKeys($new_data);
			return $db -> update($where, array('$set'=>$new_data)); # only update one row.
			#return $db -> update($where, array('$set'=>$new_data),array('multiple'=>true));
		}else{
			return self::insert($data);
		}
	}

	/**
	 */
	private static function filterKeys(&$data){
		foreach(array_keys($data) as $key){
			if(!array_key_exists($key,self::$fields)){
				unset($data[$key]);
			}
		}
	}

	/**
	 * set is_publish status by an array
	 * @param array $type_keys like array(array('type'=>'programme','keys'=>array('id'=>1)), array...)
	 * @param int $is_publish default 1
	 * @return true
	 */
	public static function setIsPublishByArray(array $type_keys,$is_publish=1){
		foreach($type_keys as $row){
			self::setIsPublish($row['type'],$row['keys'],$is_publish);
		}
		return true;
	}
	/**
	 * set is_publish status
	 * @param string $type
	 * @param array $keys like array('video_id'=>1,'language_id'=>2)
	 * @param int $is_publish default 1
	 * @return bool
	 */
	public static function setIsPublish($type,array $keys,$is_publish=1){
		$db = self::connect();
		$where = array('type'=>$type);
		foreach($keys as $k=>$v){
			$where["keys.$k"] = $v;
		}
		return $db -> update(
			$where,
			array('$set'=>array('is_publish'=>intval($is_publish))),
			array('multiple'=>true)
		);
	}


	/**
	 * delete change_log record with type and keys by an array
	 * @param array $type_keys like array(array('type'=>'video','keys'=>array('id'=>1)))
	 * @param int $is_publish default 1
	 * @return true
	 */
	public static function delTypeAndKeysLogByArray(array $type_keys,$is_publish=1){
		foreach($type_keys as $row){
			self::delTypeAndKeysLog($row['type'],$row['keys'],$is_publish);
		}
		return true;
	}
	/**
	 * delete change_log record with type and keys
	 * @param string $type
	 * @param array $keys like array('video_id'=>1,'language_id'=>2)
	 * @param int $is_publish default 1
	 * @return bool
	 */
	public static function delTypeAndKeysLog($type,$keys,$is_publish=1){
		$db = self::connect();
		$where = array('type'=>$type,'is_publish'=>intval($is_publish));
		foreach($keys as $k=>$v){
			$where["keys.$k"] = $v;
		}
		return $db -> remove($where);
	}

	/**
	 * delete change_log record by programme_id
	 * @param int $programme_id
	 * @return bool
	 */
	public static function delProgrammeLog($programme_id){
		return self::delLogsById('programme',$programme_id);
	}
	/**
	 * delete change_log record by episode_id
	 * @param int $episode_id
	 * @return bool
	 */
	public static function delEpisodeLog($episode_id,$match=true){
		if($match){
			return self::delLogsById('episode',$episode_id);
		}
		$rs = self::find(array('episode_id'=>intval($episode_id)));
		$db = self::connect();
		while($rs->hasNext()){
			$data = $rs->getNext();
			$where = array('_id'=>$data['_id']);
			if(count($data['episode_id'])>1){
				$index = array_search($episode_id,$data['episode_id']);
				unset($data['episode_id'][$index],$data['_id']);
				$data['episode_id'] = array_values($data['episode_id']);
				$db -> update($where,array('$set'=>$data));
			}else{
				$db -> remove($where);
			}
		}
		return true;
	}


	/**
	 * get change_log records by programme_id
	 * @param int $programme_id
	 * @return array
	 */
	public static function getLogsByProgrammeId($programme_id){
		return self::getLogsById('programme',$programme_id);
	}
	/**
	 * get change_log records by episode_id 
	 * @param int $episode_id
	 * @return array
	 */
	public static function getLogsByEpisodeId($episode_id){
		return self::getLogsById('episode',$episode_id);
	}


	/**
	 * private function for get logs by id
	 */
	private static function getLogsById($type,$id){
		$db = self::connect();
		$rs = $db -> find(array('is_publish'=>0,"{$type}_id"=>intval($id)));
		$data = array();
		while($rs->hasNext()){
			$d = $rs->getNext();
			self::filterKeys($d);
			$data[] = $d;
		}
		return $data;	
	}
	/**
	 * private function for del logs by id
	 */
	private static function delLogsById($type,$id){
		$db = self::connect();
		return $db -> remove(array('is_publish'=>1,"{$type}_id"=>intval($id)));
	}

	/*
	 * by donald
	 */
	public static function get(array $params)
	{
		foreach ($params as $key => $value) {
			switch ($key) {
				case 'programme_id':
				case 'episode_id':
					$params[$key] = intval($value);
					break;
			}
		}

		$db = self::connect();
		$rs = $db->find($params);
		$data = array();
		while($rs->hasNext()){
			$d = $rs->getNext();
			self::filterKeys($d);
			$data[] = $d;
		}
		return $data;	
	}
}
?>
